//
//  BLEManager.m
//  Gas Monitor
//
//  Created by 郑青松 on 2017/10/30.
//  Copyright © 2017年 Mac. All rights reserved.
//

#import "BLEManager.h"
static BLEManager *__BLEManager = nil;
@interface BLEManager (){
    //系统蓝牙设备管理对象，可以把他理解为主设备，通过他，可以去扫描和链接外设
    CBCentralManager *manager;
    //用于保存被发现设备
}

@end
@implementation BLEManager
+(id)sharedBLEManager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (__BLEManager == nil) {
            __BLEManager = [[BLEManager alloc] init];
            __BLEManager.unConnectArray = [NSMutableArray array];
            __BLEManager.connectedArray = [NSMutableArray array];
        }
    });
    return __BLEManager;
}
-(void)startScan{
    if (_connectedArray == nil)
    {
        _connectedArray = [[NSMutableArray alloc]init];
    }
    if (manager == nil)
    {
        //初始化蓝牙连接对象
        manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
    }else{
        [self reScan];
    }
}
-(void)cannotConnect
{

    [[NSNotificationCenter defaultCenter] postNotificationName:@"disconnectDevice" object:self userInfo:nil];
}
-(void)sendclick{
    //NSString * str = @"#WA=70 ";
    if (_reTime > 30)
    {
        NSDictionary * dic  = [NSDictionary dictionaryWithObject:@"data" forKey:@"un"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"bleDataSent" object:self userInfo:dic];

    }
    
    if (_isConnected == YES)
    {
        //直接发送0x02 还是要把这个换成二进制数字NSIntager
        
        //0x02
        //0x03
        //两条数据返回值拼接成一个完整数据,
        // 这里数据是拼接成了数组,新项目可以拼接成一个完整的字符串(也可能不是拼接成字符串)转成NSData,然后进行读写操作
        NSArray * readArr = @[@"#RF=? ",@"#RV=? ",@"#RA=? ",@"#RH=? ",@"#RB=? ",@"#RL=? "];
        for (int i = 0 ; i < readArr.count; i ++)
        {
            _reTime++;
            NSData * senddata = [readArr[i] dataUsingEncoding:NSUTF8StringEncoding];
            //写入和读取时用不同的characteristic(fff1和fff2)
            [self writeCharacteristic:_nowperipheral characteristic:_characteristic3 value:senddata];
        }
    }
}

// 写入的方法,新项目需要多个方法来对应多个写入操作(比如数据清零/关闭呼吸灯)
-(void)resetBeginValueWithBeginStr:(NSString *)beginStr LeakStr:(NSString *)leakStr
{
    CGFloat beginF =[beginStr floatValue];
    CGFloat leakF =[leakStr floatValue];
    NSString * str = [NSString stringWithFormat:@"#WA=%f ",beginF*1000];
    NSData * senddata = [str dataUsingEncoding:NSUTF8StringEncoding];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self writeCharacteristic:_nowperipheral characteristic:_characteristic3 value:senddata];
    });
    NSString * str1 = [NSString stringWithFormat:@"#WL=%.0f ",leakF*1000];
    NSData * senddata1 = [str1 dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",str1);

    [self writeCharacteristic:_nowperipheral characteristic:_characteristic3 value:senddata1];
}

-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            NSLog(@">>>CBCentralManagerStateUnknown");
            [self cannotConnect];
            break;
        case CBCentralManagerStateResetting:
            NSLog(@">>>CBCentralManagerStateResetting");
            [self cannotConnect];
            break;
        case CBCentralManagerStateUnsupported:
            NSLog(@">>>CBCentralManagerStateUnsupported");
            [self cannotConnect];
            break;
        case CBCentralManagerStateUnauthorized:
            NSLog(@">>>CBCentralManagerStateUnauthorized");
            [self cannotConnect];
            break;
        case CBCentralManagerStatePoweredOff:
            NSLog(@">>>CBCentralManagerStatePoweredOff");
            [self cannotConnect];
            break;
        case CBCentralManagerStatePoweredOn:
            NSLog(@">>>CBCentralManagerStatePoweredOn");
            //开始扫描周围的外设
            [central scanForPeripheralsWithServices:nil options:nil];
            
            break;
        default:
            break;
    }
}
-(void)reScan{
    [manager scanForPeripheralsWithServices:nil options:nil];
}
//扫描到设备会进入方法
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    //NSLog(@"当扫描到设备:%@",peripheral.name);
    /*
     一个主设备最多能连7个外设，每个外设最多只能给一个主设备连接,连接成功，失败，断开会进入各自的委托
     - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//连接外设成功的委托
     - (void)centra`lManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外设连接失败的委托
     - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//断开外设的委托
     */
    //找到的设备必须持有它，否则CBCentralManager中也不会保存peripheral，那么CBPeripheralDelegate中的方法也不会被调用！！

    
    NSLog(@"HHHHHHHHHHH %@",peripheral.name);
    if (_nowperipheral == nil)
    {
        if ([peripheral.name hasPrefix:@"SIAR"]||[peripheral.name hasPrefix:@"5806G"]||[peripheral.name hasPrefix:@"ABC"])
        {
            //NSLog(@"$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$*$");
            //扫秒到名称符合条件的设备添加到设备列表 发送通知
            [_connectedArray insertObject:peripheral atIndex:0];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"NewDevice" object:self userInfo:nil];
            
        }
    }
    else
    {
        //非正常状态断开的设备重新扫描到之后 直接重连 重新持有
        if (_nowperipheral.name == peripheral.name)
        {
            _nowperipheral = peripheral;
            [manager connectPeripheral:_nowperipheral options:nil];
        }
    }

}
//手动点击设备列表中的某个设备走的代理方法
-(void)connectWithDevice:(CBPeripheral *)device{
    //点击链接 先持有在连接
    _nowperipheral = device;
    //nowperipheral.delegate = self;
    [manager connectPeripheral:_nowperipheral options:nil];
}

//连接到Peripherals-失败
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@">>>连接到名称为（%@）的设备-失败,原因:%@",[peripheral name],[error localizedDescription]);
    [self cannotConnect];
    manager = nil;
}

//Peripherals断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    NSLog(@">>>外设连接断开连接 %@: %@\n", [peripheral name], [error localizedDescription]);
    self.isConnected = NO;
    //[self cannotConnect];
    //manager = nil;
}
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@">>>连接到名称为（%@）的设备-成功",peripheral.name);
    // 要把设备的代理设置为自己
    [peripheral setDelegate:self];
    //扫描外设Services，成功后会进入方法：-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    //必须添加下面一句代码,开始搜寻服务(service,也就是ffff0)
    [peripheral discoverServices:nil];
    
}

//扫描到Services
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    //  NSLog(@">>>扫描到服务：%@",peripheral.services);
    if (error)
    {
        //NSLog(@">>>Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
        return;
    }
    //项目中的ffff0
    for (CBService *service in peripheral.services) {
        //NSLog(@"%@",service.UUID);
        //扫描每个service的Characteristics，扫描到后会进入方法： -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
        [peripheral discoverCharacteristics:nil forService:service];
    }
    
}

//扫描到Characteristics  新项目一读一写两个角色  fff1(读) 和fff2(写)
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    if (error)
    {
        NSLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
        return;
    }
    for (CBCharacteristic *characteristic in service.characteristics)
    {
        NSLog(@"&*&*&*&*&*%@",characteristic.UUID);

        //项目中的fff1(读) 和fff2(写)

        //[CBUUID UUIDWithString:@"49535343-1E4D-4BD9-BA61-23C647249616"]
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"49535343-1E4D-4BD9-BA61-23C647249616"]])
        {
            NSLog(@"&*&*&*&*&*");
            //持有角色 新项目一读一写两个角色都要持有
            _characteristic3 = characteristic;
            [self notifyCharacteristic:_nowperipheral characteristic:_characteristic3];
            self.isConnected = YES;
            // 这里要定时去读数据,来刷新当前页面
            NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendclick) userInfo:nil repeats:YES];
            //[self sendclick];
        }
    }
    //获取Characteristic的值，读到数据会进入方法：-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    for (CBCharacteristic *characteristic in service.characteristics){
        {
            [peripheral readValueForCharacteristic:characteristic];
        }
    }
    //搜索Characteristic的Descriptors，读到数据会进入方法：-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    for (CBCharacteristic *characteristic in service.characteristics){
        [peripheral discoverDescriptorsForCharacteristic:characteristic];
    }
}

/**
 重中之重的方法
 */
//获取的charateristic的值
//从蓝牙设备接收所有数据,比如写入之后的结果反馈,所有读取的信息也在这里
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    //打印出characteristic的UUID和值
    //!注意，value的类型是NSData，具体开发时，会根据外设协议制定的方式去解析数据
    //NSLog(@"characteristic uuid:%@  value:%@",characteristic.UUID,characteristic.value);
    
    //接收数据 处理数据 多条数据需要手动拼接
    // 另外需要注意:不同页面需要处理的数据不同,通知给其他页面的也不同,需要根据某条数据是否存在来判断是哪个页面的数据源
    if (characteristic == _characteristic3)
    {
        _reTime = 0;
        NSData *data = characteristic.value;
        NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        //NSLog(@"*&*&*&*&*&*%@",str);
        NSString *str1 = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
        str1 = [str1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //去除掉首尾的空白字符和换行字符
        str1 = [str1 stringByReplacingOccurrencesOfString:@"\r" withString:@""];
        str1 = [str1 stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        str1 = [str1 stringByReplacingOccurrencesOfString:@";" withString:@""];
        NSArray * array = [str1 componentsSeparatedByString:@"="];
        NSArray * arr = [str1 componentsSeparatedByString:@":"];
        if (array.count > 1)
        {
            NSDictionary * dic = [NSDictionary dictionaryWithObject:array[1] forKey:array[0]];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"bleDataSent" object:self userInfo:dic];
        }
        if (arr.count > 1)
        {
            NSDictionary * dic = [NSDictionary dictionaryWithObject:arr[1] forKey:arr[0]];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"resetDevice" object:self userInfo:dic];
        }
    }
    //新项目需要判断characteristic 若是写入数据的回调要从fff2中接收
}

//搜索到Characteristic的Descriptors
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    //打印出Characteristic和他的Descriptors
    //NSLog(@"characteristic uuid:%@",characteristic.UUID);
    for (CBDescriptor *d in characteristic.descriptors) {
        //NSLog(@"Descriptor uuid:%@",d.UUID);
    }
}
//获取到Descriptors的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    //打印出DescriptorsUUID 和value
    //这个descriptor都是对于characteristic的描述，一般都是字符串，所以这里我们转换成字符串去解析
    //NSLog(@"characteristic uuid:%@  value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);
}

//写数据 ,读跟写都是走这个方法,但是读跟写的characteristic(角色)不一样
//peripheral为连接到的蓝牙设备 写操作时characteristic为fff2,读操作时characteristic为fff1
-(void)writeCharacteristic:(CBPeripheral *)peripheral
            characteristic:(CBCharacteristic *)characteristic
                     value:(NSData *)value{
    NSLog(@"%lu", (unsigned long)characteristic.properties);
    //只有 characteristic.properties 有write的权限才可以写
    if(characteristic.properties & CBCharacteristicPropertyWrite){
        /*
         最好一个type参数可以为CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,区别是是否会有反馈
         */
        NSLog(@"该字段可写！");
        [peripheral writeValue:value forCharacteristic:_characteristic3 type:CBCharacteristicWriteWithResponse];

    }else{
        NSLog(@"该字段不可写！");
    }
}
/** 写入数据回调 */
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {
    //NSLog(@"写入成功");
}

//设置通知
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
             characteristic:(CBCharacteristic *)characteristic{
    //设置通知，数据通知会进入：didUpdateValueForCharacteristic方法
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
}

//取消通知
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
                   characteristic:(CBCharacteristic *)characteristic{
    [peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
//停止扫描并断开连接
-(void)disconnectPeripheral:(CBCentralManager *)centralManager
                 peripheral:(CBPeripheral *)peripheral{
    //停止扫描
    [centralManager stopScan];
    //断开连接
    [centralManager cancelPeripheralConnection:peripheral];
}
-(void)disConnectDevice{
    if (_characteristic3 != nil)
    {
        [self cancelNotifyCharacteristic:_nowperipheral characteristic:_characteristic3];
    }
    [self disconnectPeripheral:manager peripheral:_nowperipheral];
    //[manager stopScan];
    //manager = nil;
    _nowperipheral = nil;
    _characteristic3 = nil;
    [_connectedArray removeAllObjects];
}

@end
